﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Media;
using System.Resources;
using System.Threading;
using System.Windows.Forms;
using Notas.components;
using Notas.Properties;

namespace Notas
{
    public partial class Main : Form
    {
        private Escala _escala;
        private List<Nota> _notas = new List<Nota>();
        private Dictionary<string, PointF> _positions = new Dictionary<string, PointF>();

        private Bitmap _imgClave;
        private Nota _notaSelecionada;

        private Clave _claveSelecionada;
        private Armadura _armaduraSelecionada;
        private Tom _tomSelecionado;

        public Main()
        {
            InitializeComponent();
            btnEscalaC.Checked = true;

            _claveSelecionada = Clave.G;
            _armaduraSelecionada = Armadura.C;
            _tomSelecionado = Tom.Maior;

            CarregaClave(Clave.G, Armadura.C);
            PreparePositions(Clave.G, Armadura.C);



            _escala = new Escala("C", "G") { Notas = _notas };

            RandomizeNota();
        }

        private void CarregaClave(Clave clave, Armadura nota)
        {

            ResourceManager rm = Resources.ResourceManager;
            _imgClave = (Bitmap)rm.GetObject(string.Format("{0}_{1}", clave, nota));
            imgMain.Image = _imgClave;
        }

        private void PopulaNotas()
        {
            ResourceManager rm = Resources.ResourceManager;
            
            var tmp = (string)rm.GetObject(string.Format("Escala_{0}_{1}", _claveSelecionada, _armaduraSelecionada));
            var escala = tmp.Split(',');
            
            _notas = new List<Nota>
                         {
                             new Nota(escala[0], _positions["E1"]),
                             new Nota(escala[1], _positions["F1"]),
                             new Nota(escala[2], _positions["G1"]),
                             new Nota(escala[3], _positions["A1"]),
                             new Nota(escala[4], _positions["B1"]),
                             new Nota(escala[5], _positions["C1"]),
                             new Nota(escala[6], _positions["D1"]),
                             new Nota(escala[7], _positions["E2"]),
                             new Nota(escala[8], _positions["F2"]),
                             new Nota(escala[9], _positions["G2"]),
                             new Nota(escala[10], _positions["A2"]),
                             new Nota(escala[11], _positions["B2"]),
                             new Nota(escala[12], _positions["C2"]),
                             new Nota(escala[13], _positions["D2"]),
                             new Nota(escala[14], _positions["E3"]),
                             new Nota(escala[15], _positions["F3"]),
                             new Nota(escala[16], _positions["G3"]),
                             new Nota(escala[17], _positions["A3"]),
                             new Nota(escala[18], _positions["B3"]),
                             new Nota(escala[19], _positions["C3"]),
                             new Nota(escala[20], _positions["D3"]),
                             new Nota(escala[21], _positions["E4"]),
                             new Nota(escala[22], _positions["F4"]),
                             new Nota(escala[23], _positions["G4"]),
                             new Nota(escala[24], _positions["A4"]),
                             new Nota(escala[25], _positions["B4"]),
                             new Nota(escala[26], _positions["C4"]),
                             new Nota(escala[27], _positions["D4"]),
                             new Nota(escala[28], _positions["E5"])
                         };
        }

        private void PreparePositions(Clave clave, Armadura nota)
        {
            const int x = 215;

            _positions = new Dictionary<string, PointF>
                             {
                                 {"E1", new PointF(x, 168)},
                                 {"F1", new PointF(x, 162)},
                                 {"G1", new PointF(x, 157)},
                                 {"A1", new PointF(x, 150)},
                                 {"B1", new PointF(x, 144)},
                                 {"C1", new PointF(x, 138)},
                                 {"D1", new PointF(x, 133)},
                                 {"E2", new PointF(x, 127)},
                                 {"F2", new PointF(x, 122)},
                                 {"G2", new PointF(x, 116)},
                                 {"A2", new PointF(x, 110)},
                                 {"B2", new PointF(x, 104)},
                                 {"C2", new PointF(x, 98)},
                                 {"D2", new PointF(x, 92)},
                                 {"E3", new PointF(x, 86)},
                                 {"F3", new PointF(x, 80)},
                                 {"G3", new PointF(x, 74)},
                                 {"A3", new PointF(x, 68)},
                                 {"B3", new PointF(x, 63)},
                                 {"C3", new PointF(x, 57)},
                                 {"D3", new PointF(x, 51)},
                                 {"E4", new PointF(x, 45)},
                                 {"F4", new PointF(x, 40)},
                                 {"G4", new PointF(x, 33)},
                                 {"A4", new PointF(x, 27)},
                                 {"B4", new PointF(x, 21)},
                                 {"C4", new PointF(x, 16)},
                                 {"D4", new PointF(x, 11)},
                                 {"E5", new PointF(x, 4)}
                             };
            PopulaNotas();
        }

        private void btnEscalaChange(object sender, EventArgs e)
        {
            var escalaSelecionada = ((ToolStripRadioButtonMenuItem)sender).Tag;
            Armadura escala = Armadura.A;
            switch (escalaSelecionada.ToString())
            {
                case "A":
                    escala = Armadura.A;
                    break;

                case "Bb":
                    escala = Armadura.Bb;
                    break;

                case "B":
                    escala = Armadura.B;
                    break;

                case "C":
                    escala = Armadura.C;
                    break;

                case "Db":
                    escala = Armadura.Db;
                    break;

                case "D":
                    escala = Armadura.D;
                    break;

                case "Eb":
                    escala = Armadura.Eb;
                    break;

                case "E":
                    escala = Armadura.E;
                    break;

                case "F":
                    escala = Armadura.F;
                    break;

                case "F#":
                    escala = Armadura.Fs;
                    break;

                case "G":
                    escala = Armadura.G;
                    break;

                case "Ab":
                    escala = Armadura.Ab;
                    break;
            }

            _armaduraSelecionada = escala;


            CarregaClave(_claveSelecionada, _armaduraSelecionada);
            PreparePositions(_claveSelecionada, _armaduraSelecionada);
            PopulaNotas();

            _escala = new Escala(_armaduraSelecionada.ToString(), _claveSelecionada.ToString()) { Notas = _notas };
            string[] tmp = Util.MontaEscala(_armaduraSelecionada, Tom.Maior);
            RandomizeNota();
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void ProcessButtonClick(object sender, EventArgs e)
        {
            //Verifico se acertou
            ChecaNota((Button)sender);

            //Exibo outra nota
            RandomizeNota();
        }

        private void RandomizeNota()
        {
            var number = new Random();
            int randnum = number.Next(_escala.Notas.Count);

            _notaSelecionada = _escala.Notas.ToArray()[randnum];

            Bitmap semibreve = Resources.semibreve;
            CarregaClave(_claveSelecionada, _armaduraSelecionada);
            Bitmap img = _imgClave;
            Graphics g = Graphics.FromImage(img);

            g.DrawImage(semibreve, _notaSelecionada.Posicao);
            Console.WriteLine("Nota: " + _notaSelecionada.Nome);

            imgMain.Image = img;

            GC.Collect();
            GC.WaitForPendingFinalizers();

        }

        private void ChecaNota(Control button)
        {
            var nota = button.Text;
            if (button.Text.Equals(_notaSelecionada.Nome))
            {
                button.BackColor = Color.Green;
                SystemSounds.Exclamation.Play();
            }
            else
            {
                button.BackColor = Color.Red;
                SystemSounds.Beep.Play();

                var img = imgMain.Image;
                Graphics g = Graphics.FromImage(img);
                g.DrawString(_notaSelecionada.Nome, new Font("Arial", 25), new SolidBrush(Color.Red), 10, 10);
                imgMain.Image = img;
            }

            Application.DoEvents();
            Thread.Sleep(1500);

            RandomizeNota();
            button.BackColor = SystemColors.Control;
        }

        private void btnSair_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void btnSobre_Click(object sender, EventArgs e)
        {
            new Sobre().ShowDialog();
        }
    }

    internal class Nota
    {
        public string Nome;
        public PointF Posicao;

        public Nota(string nome, PointF posicao)
        {
            Nome = nome;
            Posicao = posicao;
        }
    }

    internal class Escala
    {
        public string Clave;
        public string Nome;
        public List<Nota> Notas = new List<Nota>();

        public Escala(string nome, string clave)
        {
            Nome = nome;
            Clave = clave;
        }
    }
}